MODULE_NAME='Weather'
(
	Dev dvIP_Connection,
	Dev daTPs[],
	Integer nButtons[],
	Integer nTextChans[],
	Integer nFeedbackChans[],
	Char strZipCode[][],
	Integer nMaxZipCodes
)
(***********************************************************)
(***********************************************************)
(*  FILE_LAST_MODIFIED_ON: 04/04/2006  AT: 11:33:16        *)
(***********************************************************)
(* System Type : NetLinx                                   *)
(***********************************************************)
(* REV HISTORY:                                            *)
(***********************************************************)
(*
    $History: $
*)    
#DEFINE DEBUG
(***********************************************************)
(*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_DEVICE

(***********************************************************)
(*               CONSTANT DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_CONSTANT
cnMaxDebugLen = 200;

cnIPAddress = 'www.paragonintranet.com'

LONG lPollTImeLineID = 1;
LONG lPollTimelineTimes[] = {1200000};
(***********************************************************)
(*              DATA TYPE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_TYPE

(***********************************************************)
(*               VARIABLE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_VARIABLE
Volatile Char strData[20000]
Volatile SInteger sIPResult

Volatile Integer nIsCelsius	// high if set to celsius and low for fahrenheit
Volatile SInteger nTemperature	// current outdoor temp
Volatile Integer nHumidity	// current humidity
Volatile Integer nMode	// modes would be something like "scattered thunderstorms".  drives mutli mode button
Volatile SInteger nWindChill	// current temperature with windchill
Volatile SInteger nDay_1_ForecastHigh	// tomorrows data
Volatile SInteger nDay_1_ForecastLow
Volatile Integer nDay_1_ForecastMode
Volatile SInteger nDay_2_ForecastHigh	// day after tomorrows data
Volatile SInteger nDay_2_ForecastLow
Volatile Integer nDay_2_ForecastMode

Volatile Char strCondition[100]	// string output of mode
Volatile Char strImageFilename[100]	// not sure what this would be used for
Volatile Char strVisibility[100]	// distance you can see in theory
Volatile Char strWind[100]	// wind speed and direction
Volatile Char strPressure[100]	// barometer reading and trend
Volatile Char strSunrise[100]	// time of sunrise
Volatile Char strSunset[100]	// time of sunset
Volatile Char strCurrentLocation[100]	// location of the zip code that was feed
Volatile Char strDay_1_ForecastDay[100]	// tomorrows data
Volatile Char strDay_1_ForecastCondition[100]
Volatile Char strDay_2_ForecastDay[100]	// day after tomorrow
Volatile Char strDay_2_ForecastCondition[100]
Volatile Char strLastUpdated[100]	// last time the data was refreshed
Volatile Char strScaleText

Volatile Integer nCurrentZipCode
(***********************************************************)
(*               LATCHING DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_LATCHING

(***********************************************************)
(*       MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW           *)
(***********************************************************)
DEFINE_MUTUALLY_EXCLUSIVE

(***********************************************************)
(*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
(***********************************************************)
(* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *)
(* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *)

Define_Call 'DEBUG_OUTPUT' (Integer nLine, Char strData[])
{
	#IF_DEFINED DEBUG
	Char strTempData[200];
	Integer nLen, nCurrentPos;
	
	nLen = Length_String(strData)
	If (nLen < cnMaxDebugLen)
	{
		Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strData";
	}
	Else
	{
		strTempData = Left_String(strData,cnMaxDebugLen);
		Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strTempData";
		nCurrentPos = cnMaxDebugLen
		While (nLen > nCurrentPos)
		{
			strData = Mid_String(strData,nCurrentPos,cnMaxDebugLen);
			nCurrentPos = nCurrentPos + cnMaxDebugLen
			Send_String 0,"'Continued: ',strData";
		}
	}
	#END_IF
}

(***********************************************************)
(*                STARTUP CODE GOES BELOW                  *)
(***********************************************************)
DEFINE_START

nCurrentZipCode = 1 // default
Timeline_Create(lPollTimeLineID,lPollTimelineTimes,1,Timeline_Absolute,Timeline_Repeat)
Wait 500 // since the timeline wont start for 20 minutes lets get initial data.
    sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);

(***********************************************************)
(*                THE EVENTS GO BELOW                      *)
(***********************************************************)
DEFINE_EVENT
Button_Event[daTPs,nButtons] 
{
    Push:  
    {
	Switch (Get_last(nButtons))
	{
	    Case 1: // this will force it to request the data in celsius format
	    {
		strScaleText = 'c';
		strData = '';
		sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);
	    }
	    Case 2: // this will force it to request the data in fahrenheit format
	    {
		strScaleText = 'f';
		strData = '';
		sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);
	    }
	    Case 3:
	    {
		sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);
		Timeline_Create(lPollTimeLineID,lPollTimelineTimes,1,Timeline_Absolute,Timeline_Repeat)
		Call 'DEBUG_OUTPUT' (__LINE__,"'Created timeline.'");
	    }
	    Case 4:
	    {
		strData = '';
		nCurrentZipCode++
		If (nCurrentZipCode > nMaxZipCodes)
		    nCurrentZipCode = 1
		Call 'DEBUG_OUTPUT' (__LINE__,"'nCurrentZipCode:',Itoa(nCurrentZipCode)");
		sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);
	    }
	}
    }
}

Data_Event[daTPs]
{
    Online:
    {
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[1]),'-',Itoa(nTemperature)"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[2]),'-',Itoa(nHumidity)"
	Send_Command Data.Device,"'^ICO-',Itoa(nTextChans[3]),',0,',Itoa(nMode+300)"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[4]),'-',Itoa(nWindChill)"	
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[5]),'-',Itoa(nDay_1_ForecastHigh)"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[6]),'-',Itoa(nDay_1_ForecastLow)"
	Send_Command Data.Device,"'^ICO-',Itoa(nTextChans[7]),',0,',Itoa(nDay_1_ForecastMode+300)"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[8]),'-',Itoa(nDay_2_ForecastHigh)"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[9]),'-',Itoa(nDay_2_ForecastLow)"
	Send_Command Data.Device,"'^ICO-',Itoa(nTextChans[10]),',0,',Itoa(nDay_2_ForecastMode+300)"
    

	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[11]),'-',strCondition"
	// rdm this will need to be changed to match the panel
	//Send_Command daTPs,"'TEXT',Itoa(nTextChans[12]),'-',strImageFilename"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[13]),'-',strVisibility"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[14]),'-',strWind"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[15]),'-',strPressure"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[16]),'-',strSunrise"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[17]),'-',strSunset"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[18]),'-',strCurrentLocation"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[19]),'-',strDay_1_ForecastDay"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[20]),'-',strDay_1_ForecastCondition"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[21]),'-',strDay_2_ForecastDay"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[22]),'-',strDay_2_ForecastCondition"
	Send_Command Data.Device,"'TEXT',Itoa(nTextChans[23]),'-',strLastUpdated"
    }
}

Timeline_Event[lPollTImeLineID]
{
    sIPResult = IP_Client_Open(dvIP_Connection.Port, cnIPAddress, 80, IP_TCP);
}

Data_Event[dvIP_Connection]	// internet data in
{
    Online:
    {
	If (strScaleText != 'f' && strScaleText != 'c')
	{
	    strScaleText = 'f';
	}
	Send_String dvIP_Connection,"'GET /exec/weather/?zip=',strZipCode[nCurrentZipCode],'&units=',strScaleText,' HTTP/1.1',13,10,'Host:www.paragonintranet.com',13,10,13,10"; 
	Call 'DEBUG_OUTPUT' (__LINE__,"'GET /exec/weather/?zip=',strZipCode[nCurrentZipCode],'&units=',strScaleText,' HTTP/1.1',13,10,'Host:www.paragonintranet.com',13,10,13,10");
    }
    String:
    {
	Stack_Var Integer	nI;																		// used for indexing in for loop
	Stack_Var Char strTrash[50],strTemp[24][100]

	strData = "strData,Data.Text"
	Call 'DEBUG_OUTPUT' (__LINE__,"'Data.Text=',Data.Text");
	If (Find_String(strData,'EOF',1))	// gather all data
	{
	    IP_Client_Close(dvIP_Connection.Port)
	    Call 'DEBUG_OUTPUT' (__LINE__,"'Data=',strData");
	    strTrash = Remove_String(strData,'(*)(*)',1);	// remove as much header data as we can
	    For(nI=1; nI <= 24; nI++)				// tokenize all the data into temp[]
	    {
		If(Find_String(strData,'~',1))				// ~ seperates all items
		{
		    strTemp[nI] = Remove_String(strData,'~',1);		// remove the data and store it in temp[]
		    strTemp[nI] = Left_String(strTemp[nI],Length_String(strTemp[nI])-1);	// remove the ~ from the string
		    Call 'DEBUG_OUTPUT' (__LINE__,"'Temp[',Itoa(nI),']=',strTemp[nI]");		// diagnostic data
		}
		Else
		{
		    Call 'DEBUG_OUTPUT' (__LINE__,"'Weather failed to receive an entire string.  Only found ',Itoa(nI),' elements'");
		    nI = 0;		// sets i to 0 so that we know we dont have valid data
		    Break;		// exit out of the for loop
		}
	    }
	    strData = '';		// get rid of any left over data in the buffer

	    Call 'DEBUG_OUTPUT' (__LINE__,"'weather i=',Itoa(nI)");
	    If (nI = 25) 		// if it is 24 it must have completed.
	    {
		Call 'DEBUG_OUTPUT' (__LINE__,"'Weather parsed complete string.'");
		If (strTemp[1] = 'f')	// fahrenheit
		{
		    nIsCelsius = 0;
		}
		Else If (strTemp[1] = 'c')	// celsius
		{
		    nIsCelsius = 1;
		}
		Else	// error condition
		{
		    nIsCelsius = 0;
		    Call 'DEBUG_OUTPUT' (__LINE__,"'Weather found an invalid scale:',strTemp[1]");
		}

		// populate all of the analog joins
		nTemperature = Atoi(strTemp[2]);
		nHumidity = Atoi(strTemp[4]);
		nMode = Atoi(strTemp[6]);
		nWindChill = Atoi(strTemp[7]);
		nDay_1_ForecastHigh = Atoi(strTemp[15]);
		nDay_1_ForecastLow = Atoi(strTemp[16]);
		nDay_1_ForecastMode = Atoi(strTemp[18]);
		nDay_2_ForecastHigh = Atoi(strTemp[20]);
		nDay_2_ForecastLow = Atoi(strTemp[21]);
		nDay_2_ForecastMode = Atoi(strTemp[23]);
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[1]),'-',Itoa(nTemperature)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[2]),'-',Itoa(nHumidity)"
		Send_Command daTPs,"'^ICO-',Itoa(nTextChans[3]),',0,',Itoa(nMode+300)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[4]),'-',Itoa(nWindChill)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[5]),'-',Itoa(nDay_1_ForecastHigh)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[6]),'-',Itoa(nDay_1_ForecastLow)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[7]),'-',Itoa(nDay_1_ForecastMode)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[8]),'-',Itoa(nDay_2_ForecastHigh)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[9]),'-',Itoa(nDay_2_ForecastLow)"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[10]),'-',Itoa(nDay_2_ForecastMode)"
		
		// populate all of the serial outputs
		strCondition = strTemp[3];
		strImageFilename = strTemp[5];
		strVisibility = strTemp[8];
		strWind = strTemp[9];
		strPressure = strTemp[10];
		strSunrise = strTemp[11];
		strSunset = strTemp[12];
		strCurrentLocation = strTemp[13];
		strDay_1_ForecastDay = strTemp[14];
		strDay_1_ForecastCondition = strTemp[17];
		strDay_2_ForecastDay = strTemp[19];
		strDay_2_ForecastCondition = strTemp[22];
		strLastUpdated = strTemp[24];
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[11]),'-',strCondition"
		// rdm this will need to be changed to match the panel
		//Send_Command daTPs,"'TEXT',Itoa(nTextChans[12]),'-',strImageFilename"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[13]),'-',strVisibility"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[14]),'-',strWind"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[15]),'-',strPressure"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[16]),'-',strSunrise"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[17]),'-',strSunset"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[18]),'-',strCurrentLocation"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[19]),'-',strDay_1_ForecastDay"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[20]),'-',strDay_1_ForecastCondition"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[21]),'-',strDay_2_ForecastDay"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[22]),'-',strDay_2_ForecastCondition"
		Send_Command daTPs,"'TEXT',Itoa(nTextChans[23]),'-',strLastUpdated"
	    }                                            
	}
    }
}

(***********************************************************)
(*            THE ACTUAL PROGRAM GOES BELOW                *)
(***********************************************************)
DEFINE_PROGRAM

(***********************************************************)
(*                     END OF PROGRAM                      *)
(*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
(***********************************************************)
